package br.com.felinelayer.client.clientSwing;

import br.com.felinelayer.common.Message;
import br.com.felinelayer.common.Protocol;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;

/**
 *
 */
public abstract class Component<T extends br.com.felinelayer.client.IComponent>
        extends br.com.felinelayer.client.Component<T> implements FocusListener {

    public static final int HEIGHT_DEFAULT = 20;
    public int id = 0;
    private Object object;
    private String previosText = "";

    @Override
    public T setId(int id) {
        this.id = id;
        return (T) this;
    }

    @Override
    public T setVisible(boolean visible) {
        if (getObject() instanceof JComponent) {
            ((JComponent) getObject()).setVisible(visible);
        }
        if (getObject() instanceof JFrame) {
            ((JFrame) getObject()).setVisible(visible);
        }
        return (T) this;
    }

    @Override
    public T setWidht(int width) {
        Dimension d = getDimension();
        d.width = width;
        setDimension(d);
        return (T) this;
    }

    @Override
    public T setHeight(int height) {
        Dimension d = getDimension();
        d.height = height;
        setDimension(d);
        return (T) this;
    }

    @Override
    public abstract T setText(String text);

    @Override
    public abstract String getText();

    @Override
    public Object getObject() {
        return object;
    }

    public T setObject(Object object) {
        this.object = object;
        if (object instanceof JComponent) {
            ((JComponent) getObject()).addFocusListener(this);
        }
        return (T) this;
    }

    public Rectangle getBounds() {
        if (getObject() instanceof JComponent) {
            return ((JComponent) getObject()).getBounds();
        }
        if (getObject() instanceof JFrame) {
            return ((JFrame) getObject()).getBounds();
        }
        return null;
    }

    public T setBounds(Rectangle rectangle) {
        if (getObject() instanceof JComponent) {
            ((JComponent) getObject()).setBounds(rectangle);
        }
        if (getObject() instanceof JFrame) {
            ((JFrame) getObject()).setBounds(rectangle);
        }
        return (T) this;
    }

    public Dimension getDimension() {
        if (getObject() instanceof JComponent) {
            return ((JComponent) getObject()).getSize();
        }
        if (getObject() instanceof JFrame) {
            return ((JFrame) getObject()).getSize();
        }
        return null;
    }

    public T setDimension(Dimension rectangle) {
        if (getObject() instanceof JComponent) {
            ((JComponent) getObject()).setSize(rectangle);
        }
        if (getObject() instanceof JFrame) {
            ((JFrame) getObject()).setSize(rectangle);
        }
        return (T) this;
    }

    public int getHeight() {
        return (int) getBounds().getHeight();
    }

    @Override
    public T setTop(int top) {
        Rectangle b = getBounds();
        b.y = top;
        setBounds(b);
        return (T) this;
    }

    @Override
    public T setLeft(int left) {
        Rectangle b = getBounds();
        b.x = left;
        setBounds(b);
        return (T) this;
    }

    protected Message createEvent(String name) throws Exception {
        return getClient().createEvent(this, name);
    }

    protected void fireEvent(String name) throws Exception {
        getClient().sendEvent(this, name);
    }

    protected T fireEvent(Message message) {
        getClient().sendMessage(message);
        return (T) this;
    }

    protected Message fireInquireEvent(Message message) {
        return getClient().inquireMessage(message);
    }

    @Override
    protected void doChangeProperty(Message message) {
    }

    @Override
    public void messageReceived(Message message) {
    }

    /**
     * Invoked when a component gains the keyboard focus.
     */
    @Override
    public void focusGained(FocusEvent e) {
        try {
            previosText = getText();
            fireEvent(Protocol.EVENT_FOCUS_ENTER);
        } catch (Exception ex) {
            try {
                Logger.getLogger(Component.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex1) {
                Logger.getLogger(Component.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }

    /**
     * Invoked when a component loses the keyboard focus.
     */
    @Override
    public void focusLost(FocusEvent e) {
        try {
            Message m = createEvent(Protocol.EVENT_FOCUS_EXIT);
            String currentText = getText();
            if (!previosText.equalsIgnoreCase(getText())) {
                m.setValueByName(Protocol.PROPERTY_NAME_TEXT, currentText);
            }
            fireEvent(m);
        } catch (Exception ex) {
            Logger.getLogger(Component.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    protected void doDestroy() {
        if (object instanceof JComponent) {
            ((JComponent) getObject()).getParent().remove((JComponent) getObject());
        }
    }
}
